package hh.engine;

import lombok.Data;

@Data
public class Reader {
    int position;
    char[] data;

    int line = 1;
    int linePosition;

    public Reader(String d) {
        this.data = d.toCharArray();
    }

    public Reader(char[] data) {
        this.data = data;
    }


    public boolean hasText() {
        return position < data.length;
    }


    // 向前推进并返回
    public char forward() {
        char c = data[position];
        linePosition++;
        if (position > 0 && data[position - 1] == '\n') {
            line++;
            linePosition = 1;
        }
        position++;
        return c;
    }

    public char back() {
        char c = data[position];
        linePosition--;
        if (data[position - 2] == '\n') {
            line--;
            linePosition = 0;
        }
        position--;
        return c;
    }

    public char peek() {
        return data[position];
    }
    public char peek(int i) {
        return data[position+i];
    }


    public boolean hasNextString(String s) {
        int pos = this.position;
        int li = this.line;
        int liPos = this.linePosition;
        int i = 0;
        char first = s.charAt(0);
        while (hasText()) {
            if (peek() == first) {
                if (match(s)) return true;
            }
            forward();
        }
        update(pos, li, liPos);
        return false;
    }

    private void update(int position, int line, int linePosition) {
        this.position = position;
        this.line = line;
        this.linePosition = linePosition;
    }

    public boolean nextChar(char c) {
        int pos = this.position;
        int li = this.line;
        int liPos = this.linePosition;
        while (hasText()) {
            if (forward() == c) {
                return true;
            }
        }
        update(pos, li, liPos);
        return false;
    }

    public boolean match(String str) {
        int pos = this.position;
        int li = this.line;
        int liPos = this.linePosition;
        if (str.length() > retainCount()) return false;
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) != forward()) {
                update(pos, li, liPos);
                return false;
            }
        }
        return true;
    }

    private int retainCount() {
        return data.length - position;
    }

    public void skipSpaces() {
        while (peek() == ' ') {
            forward();
        }
    }

    public String retainStr() {
        return new String(data, position, data.length - position);
    }
}
